﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. 
// See License.txt in the project root for license information.
using System;
using System.Cloud.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ListOfLists_WPF
{
    /// <summary>
    /// Interaction logic for InnerListControl.xaml
    /// </summary>
    public partial class InnerListControl : UserControl
    {
        private ObservableCloudList<ListItem> m_list;
        private string m_listName;
        public InnerListControl(string listName, ObservableCloudList<ListItem> list)
        {
            m_listName = listName;
            m_list = list;
            InitializeComponent();
            this.titleText.Text = m_listName;
            this.innerList.ItemsSource = m_list;
            m_list.CollectionChanged += m_list_CollectionChanged;
        }

        void m_list_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
            {
                this.ParentLayoutInvalidated(this); // Force a redraw?
            }
        }

        public string ListName { get { return m_listName; } }

        void OnNewItem(object sender, RoutedEventArgs e)
        {
            var dlg = new ListItemDialog();
            dlg.ShowDialog();
            if (dlg.Description != null)
            {
                var newItem = new ListItem() { Description = dlg.Description, Color="White" };
                m_list.Add(newItem);
            }
        }

        void OnDeleteItem(object sender, RoutedEventArgs e)
        {
            var mi = sender as MenuItem;
            if (mi != null)
            {
                var toBeRemoved = (ListItem)mi.Tag;
                var source = (IList<ListItem>)MainWindow.dragSource.ItemsSource;
                source.Remove(toBeRemoved);
            }
        }

        void OnSetColor(object sender, RoutedEventArgs e)
        {
            var mi = sender as MenuItem;
            if (mi != null)
            {
                var toBeAltered = (ListItem)mi.Tag;
                var newColor = (string)mi.Header;
                if (toBeAltered.Color.Equals(newColor)) return;
                var source = (IList<ListItem>)MainWindow.dragSource.ItemsSource;

                var idx = source.IndexOf(toBeAltered);
                toBeAltered.Color = newColor;
                source[idx] = toBeAltered;
            }
        }

        private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ListBox parent = (ListBox)sender;
            MainWindow.dragSource = parent;
            //if (dragSource == null)
            //{
            //    Console.WriteLine("Dragsource is NULL!!");
            //}
            object data = GetDataFromListBox(MainWindow.dragSource, e.GetPosition(parent));

            if (data != null)
            {
                DragDrop.DoDragDrop(parent, data, DragDropEffects.Move);
            }
        }
        private void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            ListBox parent = (ListBox)sender;
            MainWindow.dragSource = parent;
        }

        #region GetDataFromListBox(ListBox,Point)
        private static object GetDataFromListBox(ListBox source, Point point)
        {
            UIElement element = source.InputHitTest(point) as UIElement;
            if (element != null)
            {
                object data = DependencyProperty.UnsetValue;
                while (data == DependencyProperty.UnsetValue)
                {
                    data = source.ItemContainerGenerator.ItemFromContainer(element);

                    if (data == DependencyProperty.UnsetValue)
                    {
                        element = VisualTreeHelper.GetParent(element) as UIElement;
                    }

                    if (element == source)
                    {
                        return null;
                    }
                }

                if (data != DependencyProperty.UnsetValue)
                {
                    return data;
                }
            }

            return null;
        }

        #endregion 

        private async void OnDrop(object sender, DragEventArgs e)
        {
            if (sender == MainWindow.dragSource)
            {
                e.Handled = false; // Allow for continued routing of the event?
                return; // Don't allow drags from a list to itself
            }
            ListBox parent = (ListBox)sender;
            ListItem data = (ListItem)e.Data.GetData(typeof(ListItem));

            await Task.Factory.StartNew( () =>
                {
                    ((IList<ListItem>)MainWindow.dragSource.ItemsSource).Remove(data);
                }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
            data.UpdateTime = DateTime.UtcNow;

            await Task.Factory.StartNew( () =>
                {
                    ((IList<ListItem>)parent.ItemsSource).Add(data);
                }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
        }
    }
}
